// Copyright 2011-2012, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_BOOST_XML_INTERNAL_XML_NODE_ITERATOR_IMPL_HPP_
#define LIBV_BOOST_XML_INTERNAL_XML_NODE_ITERATOR_IMPL_HPP_

#include <iterator>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/utility/enable_if.hpp>
#include <libv/boost/xml/xml_node.h>
#include <libv/check.h>



namespace libv {

// (!) Итератор возвращает временные объекты,
//     которые нужно копировать, а не сохранять по ссылке.
class XmlNode::Iterator
    : public boost::iterator_facade<XmlNode::Iterator,
                                    const XmlNode,
                                    ::std::bidirectional_iterator_tag,
                                    const XmlNode> {
  friend class XmlNode;
  friend class boost::iterator_core_access;
  private:

  public:
    // Итератор, создаваемый методом end().
    Iterator() {}

    // Возможно копирование итераторов одинаковых типов.
    Iterator(const Iterator& rhv)
        : current_(rhv.current_) {}

    // Проверка нахождения итератора в начале.
    bool AtBegin() const {
        return current_.pimpl_->previous_sibling() == NULL;
    }

    // Проверка достижения итератором конца.
    bool AtEnd() const {
        return current_.pimpl_ == NULL;
    }

  private:
    explicit Iterator(const XmlNode& parent)
      : current_(parent.pimpl_->first_node()) {}

    void increment() {
        LIBV_PRECOND(!AtEnd());
        current_.pimpl_ = current_.pimpl_->next_sibling();
    }

    void decrement() {
        LIBV_PRECOND(!AtBegin());
        LIBV_PRECOND(!AtEnd());
        current_.pimpl_ = current_.pimpl_->previous_sibling();
    }

    const XmlNode dereference() const {
        LIBV_PRECOND(!AtEnd());
        return current_;
    }

    bool equal(const Iterator& rhv) const {
        return current_ == rhv.current_;
    }

    XmlNode current_;
};

}  // libv

#endif  // LIBV_BOOST_XML_INTERNAL_XML_NODE_ITERATOR_IMPL_HPP_
